<?php

namespace app\api\Controller;

use think\Controller;
use think\Loader;
use think\Request;
use think\Log;
use think\Db;
use Whoops\Handler\PrettyPageHandler;
use Whoops\Run;
use app\service\Token;
use app\service\UserLogService;

class Common extends Controller
{
    protected $return;
    protected $params;
    protected $member;

    public function __construct(Request $request = null)
    {
        parent::__construct($request);

        if(getenv('APP_DEBUG') || getenv('APP_ENV') != 'production'){
            $whoops = new Run;
            $whoops->pushHandler(new PrettyPageHandler);
            $whoops->register();
        }
    
        // 跨域设置
        // 设置能访问的域名
        $originarr = [
            'http://www.zaimaqin.cn',
            'http://zaimaqin.cn',
            'https://www.zaimaqin.cn',
            'https://zaimaqin.cn',
            'http://im.bjtxkj88.cn'
        ];
        // 获取当前跨域域名
        $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';
        if (in_array($origin, $originarr)) {
            // 允许 $originarr 数组内的 域名跨域访问
            header('Access-Control-Allow-Origin:' . $origin);
            // 响应类型
            header('Access-Control-Allow-Methods: GET, POST, PUT,DELETE,OPTIONS,PATCH');
            // 带 cookie 的跨域访问
            header('Access-Control-Allow-Credentials: true');
            // 响应头设置
            header('Access-Control-Allow-Headers:Origin, X-Requested-With, Content-Type, Accept, Authorization');
        }
        if (!isset($_SERVER['REQUEST_METHOD'])) {
            return;
        } else if($_SERVER['REQUEST_METHOD']=='OPTIONS'){
            //exit是用来结束程序执行的,如果参数是字符串，PHP将会直接把字符串输出，
            //如果参数是整型(范围是0-254)，那个参数将会被作为结束状态使用。
            exit('options类型的请求，结束');
        }

        $this->return = changeCode(config('code'));

        $this->params = $request->param('', null, ['strip_tags', 'htmlspecialchars_decode']);

        if (isset($this->params['device_id'])) {
            $limit = db('limit_device')->where(['device_id'=>$this->params['device_id'], 'delete_time'=>0])->find();
            if ($limit) exit(json_encode(['code' => 400, 'msg' => '设备异常']));
        }

        $check = config('auth');
        $dispatch = $request->dispatch();
        $controller = strtolower($dispatch['module'][1]);
        $action = $dispatch['module'][2];

        $controllerUpper = Loader::parseName($controller,1);

        if (array_key_exists($controller, $check) || array_key_exists($controllerUpper, $check)) {

            $checkController = $check[$controller] ?? $check[$controllerUpper];
            foreach ($checkController as $key => $item) {
                $checkController[$key] = strtolower($item);
            }

            $inArray = in_array(strtolower($action), $checkController);
            if (!$checkController || ($inArray && end($checkController) != 'filter') || (!$inArray && end($checkController) == 'filter')) {
                $this->auth();
            } else {
                $this->auth(0);
            }
        } else {
            $this->auth(0);
        }

        $validate = Loader::getModuleAndClass($controller, 'validate', false);

        if (class_exists($validate[1])) {
            $validate = Loader::validate($controller);

            if ($scene = $validate->hasScene($action)) {
                if (!$validate->scene($scene)->check($this->params)) {
                    exit(json_encode(['code' => 400, 'msg' => $validate->getError()]));
                }
            }
        }
    }

    // valid 1强制验证 0不强制验证
    private function auth($valid = 1)
    {
        $return = changeCode(config('code'), '');
        
        $user_id = 0;
        // if ($valid) {
        //     $user_id = $this->params['user_id'] ?? '';
        // }

        $isTokenUser = false;

        if (empty($_SERVER['HTTP_AUTHORIZATION'])){
        }else{
            $token = $_SERVER['HTTP_AUTHORIZATION'];
            $checkToken = Token::checkToken($token, $valid);
            if ($valid || $checkToken) {
                $data = (array)$checkToken['data']['data'];
                $user_id = $data['userid'];
                $isTokenUser = true;
            }
        }
        if (!$user_id) {
            $this->apilog();
            if ($valid) {
                exit(json_encode(['code' => 400, 'msg' => $return['user.error.expired']]));
            } else {
                return false;
            }
        }

        $member_real = $member = _user($user_id);
        if ($member['reg'] == 2 && $member['authcode']) {
            $member_real = _user($member_real['authcode']);
        }

        if ($member) {
            $is_banned = false;
            if(isset($data) && $data['time'] != $member['last_login_time']){
                $this->apilog();
                if ($valid) {
                    exit(json_encode(['code' => 402, 'msg' => $return['user.error.expired']]));
                } else {
                    return false;
                }
            } else if ($member_real['is_banned']) {
                $is_banned = true;
                $this->apilog();
                if ($valid) {
                    $this->allowAccessTo($member_real);
                    // exit(json_encode(['code' => 400, 'msg' => $return['user.error.blockade']]));
                } else {
                    return false;
                }
            }

            $refresUserCacheKey = 'refreshUserState:'.$user_id;
            if (($valid||$isTokenUser) && !cache($refresUserCacheKey)) {
                $update = [
                    // 'is_online' => 1,
                    'last_login_datetime' => date('Y-m-d H:i:s')
                ];
                if ($is_banned) {
                    $update['is_online'] = 0;
                }
                // Db::name('user')->where(['id'=>$user_id])->update($update);
                // Db::name('user')->where(['reg'=>2,'authcode'=>$user_id])->update($update);
                cache($refresUserCacheKey, $update['last_login_datetime'], 60);
            }
        } else {
            $this->apilog();
            if ($valid) {
                exit(json_encode(['code' => 400, 'msg' => $return['user.error.notExist']]));
            } else {
                return false;
            }
        }
        $this->member = $member;
        $this->apilog();
    }

    private function apilog()
    {
        try {
            $logparam = [];
            if($this->member){
                $logparam['user_id'] = $this->member['id'];
            }if(isset($this->params['user_id'])){
                $logparam['user_id'] = $this->params['user_id'];
            }elseif(isset($this->params['userid'])){
                $logparam['user_id'] = $this->params['userid'];
            }
            UserLogService::add($logparam);

        } catch (\Exception $e) {
            Log::write('记录请求错误：' . $e->getMessage(), 'error');
        }
    }

    protected function pass($data, $content = 'data', $extra = [])
    {
        $field = is_string($data) && $content == 'data' ? 'msg' : $content;

        $data = ['code' => 200, $field => $data];

        $data = array_merge($data, $extra);

        return json($data);
    }

    protected function miss($msg, $code = 400)
    {
        return json(['code' => $code, 'msg' => $msg]);
    }

    protected function allowAccessTo($member){
        $bannedLog = Db::name('admin_logs')->where([
                                    'channel' => 3,
                                    'toward' => 0,
                                    'money' => 0,
                                    'user_id' => $member['id'],
                                    'content' => ['like', '封禁账号至%'],
                                    'time'  => ['>=', '2023-03-07 00:00:00']
                                ])->find();
        if (!$bannedLog) {
            exit(json_encode(['code' => 402, 'msg' => '账号被封禁，解封时间：' . $member['banned_end_time']]));
        }
        $request = Request::instance();
        $allow = [
            'api/login/index',
            'api/login/setonline',
            'api/login/checklogin',
            'api/v2.user/index',
            'api/v2.user/info',
            'api/user/info',
            'api/topup/lists',
            'api/dymanic/lists',
            'api/v2.dymanic/lists',
            'api/user/volleylists',
            'api/mall.distribution/statistics',
            'api/user/incomelists',
            'api/withdraw/lists',
            'api/withdraw/payments',
            'api/withdraw/submit',
            'api/v2.user/readrule',
            'api/member/teamdetail',
            'api/address/signtrack',
            'api/service/all',
            'api/member/teamincomelists',
            'api/member/team',
            'api/member/teamdetail',
            'api/invite/index',
            'api/address/myadd',
            'api/address/signrecords',
            'api/address/info',
            'api/address/collect',
            'api/address/collects',
            'api/member/deleteaccount'
        ];
        $apipath = $request->pathinfo();
        if(!in_array(strtolower($apipath), $allow)){
            exit(json_encode(['code' => 201, 'msg' => '账号仅支持提现']));
        }
    }
}

